package com.easy.stock.spider;

import java.io.IOException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.easy.stock.spider.SpiderTask.STATUS;
import com.easy.stock.spider.html.BaseHtmlSpider;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.Response;

/**
 * 所有spider事件处理的父类， 底层的事件处理只需要实现其中两个函数就可以。
 * 
 * @author simonlin
 */
public abstract class BaseAsyncCompletionHandler extends AsyncCompletionHandler<Response> {

	protected static Log LOG = LogFactory.getLog("spider");
	protected BaseHtmlSpider spider;
	protected SpiderTask task;
	
	/**
	 * 抓取失败的处理函数
	 * 
	 * @param t
	 */
	public abstract void doOnThrowable(Throwable t);
	
	/**
	 * 抓取成功的处理函数
	 * 
	 * @param response	返回的结果
	 * @return List<SpiderTask>	由该任务衍生出来的继续抓取的任务
	 */
	public abstract List<SpiderTask> doOnCompleted(Response response) throws IOException;

	
	@Override
	public void onThrowable(Throwable t) {
		// 修改task的状态
		task.setStatus(STATUS.FAILED);
		spider.offTask(task);
		LOG.error("exception when crawl url:"+task.getUrl()+", reason=", t);
		// 调用业务处理逻辑
		doOnThrowable(t);
	}

	@Override
	public Response onCompleted(Response response) throws Exception {
		// 调用业务逻辑
		List<SpiderTask> tasks=null;
		try {
			tasks = doOnCompleted(response);
			// 修改task的状态
			task.setStatus(STATUS.SUCCESS);
			spider.offTask(task);
		} catch (Throwable t) {
			task.setStatus(STATUS.FAILED);
			spider.offTask(task);
			LOG.error("process response url exception: "+task.getUrl()+" ,reason=", t);
			// 修改task的状态
			return response;
		}
		// 把tasks加入队列
		if(tasks!=null) {
			for(SpiderTask task : tasks) {
				spider.addTask(task);
			}
		}
		
		return response;
	}

	
	public SpiderTask getTask() {
		return task;
	}

	public void setTask(SpiderTask task) {
		this.task = task;
	}
	
	public BaseHtmlSpider getSpider() {
		return spider;
	}

	public void setSpider(BaseHtmlSpider spider) {
		this.spider = spider;
	}

}
